package com.zy.business.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zy.business.domain.*;
import com.zy.business.domain.vo.ProjectDto;
import com.zy.business.mapper.*;
import com.zy.business.service.ProjectService;
import com.zy.common.annotation.Dict;
import com.zy.common.core.domain.AjaxResult;
import com.zy.common.core.domain.TreeSelect;
import com.zy.common.core.domain.entity.SysDept;
import com.zy.common.core.domain.entity.SysUser;
import com.zy.common.utils.SecurityUtils;
import com.zy.common.utils.StringUtils;
import com.zy.system.mapper.SysDeptMapper;
import com.zy.system.mapper.SysDictDataMapper;
import com.zy.system.mapper.SysUserMapper;
import com.zy.system.service.ISysDeptService;
import io.swagger.annotations.ApiModelProperty;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.*;

/**
 * @description: 项目管理服务层实现
 * @author: whf
 * @create: 2023-01-10 14:27
 **/
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, TbProject> implements ProjectService {

    @Autowired
    private ProjectContactMapper projectContactMapper;

    @Autowired
    private ProjectProgressRateMapper progressRateMapper;

    @Autowired
    private SysDictDataMapper dictDataMapper;

    @Autowired
    private ProjectOperRecordMapper operRecordMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private DailyReportMapper dailyReportMapper;

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private ISysDeptService deptService;

    @Override
    public List<TbProject> selectProjectList(ProjectDto project) {
        return baseMapper.list(project);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addProject(TbProject project) {
        project.setCreateTime(new Date());
        int row = baseMapper.insertTbProject(project);
        if (project.getProjectContactList()!=null && project.getProjectContactList().size()>0){
            for (int i = 0; i < project.getProjectContactList().size(); i++) {
                TbProjectContact projectContact;
                projectContact = project.getProjectContactList().get(i);
                projectContact.setProjectId(project.getProjectId());
                projectContact.setCreateBy(project.getUpdateBy());
                projectContact.setCreateTime(new Date());
                if (i==0){
                    projectContact.setIsFirst(1);
                }else {
                    projectContact.setIsFirst(0);
                }
                projectContactMapper.insert(projectContact);
            }
        }
        TbProjectProgressRate projectProgressRate = new TbProjectProgressRate();
        projectProgressRate.setProjectId(project.getProjectId());
        projectProgressRate.setProgressDescription("创建项目");
        projectProgressRate.setCreateBy(project.getCreateBy());
        projectProgressRate.setCreateTime(new Date());
        progressRateMapper.insert(projectProgressRate);
        return row;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int editProject(TbProject project) {
        try {
            TbProject oldProject = baseMapper.selectById(project.getProjectId());
            String changeStr = contrastObj(oldProject, project);
            if (project.getProjectContactList()!=null && project.getProjectContactList().size()>0){
                for (TbProjectContact tbProjectContact : project.getProjectContactList()) {
                    String msg = "";
                    if (tbProjectContact.getId()!=null){
                        TbProjectContact old = projectContactMapper.selectById(tbProjectContact.getId());
                        if (!old.getName().equals(tbProjectContact.getName())){
                            msg += "联系人由'"+old.getName()+"'变更为'"+tbProjectContact.getName()+"'";

                        }
                        if (!old.getPhone().equals(tbProjectContact.getPhone())){
                            if (StringUtils.isEmpty(msg)){
                                msg += "联系人'"+old.getName()+"'的联系电话由"+old.getPhone()+"变更为'"+tbProjectContact.getPhone()+"'";
                            }else {
                                msg += "，联系电话'"+old.getPhone()+"'变更为'"+tbProjectContact.getPhone()+"'";
                            }
                        }
                        if (!old.getRemark().equals(tbProjectContact.getRemark())){
                            if (StringUtils.isEmpty(msg)){
                                msg += "联系人'"+old.getName()+"'的备注由'"+old.getRemark()+"'变更为'"+tbProjectContact.getRemark()+"'";
                            }else {
                                msg += "，备注由'"+old.getRemark()+"'变更为'"+tbProjectContact.getRemark()+"'";
                            }
                        }
                        if (!StringUtils.isEmpty(msg)){
                            tbProjectContact.setUpdateBy(project.getUpdateBy());
                            tbProjectContact.setUpdateTime(new Date());
                            tbProjectContact.setIsFirst(old.getIsFirst());
                            projectContactMapper.updateById(tbProjectContact);
                        }
                    }else {
                        TbProjectContact old = projectContactMapper.selectOne(new QueryWrapper<TbProjectContact>().eq("project_id",project.getProjectId()).eq("is_first",1));
                        tbProjectContact.setCreateBy(project.getUpdateBy());
                        tbProjectContact.setCreateTime(new Date());
                        tbProjectContact.setProjectId(project.getProjectId());
                        if (old==null){
                            tbProjectContact.setIsFirst(1);
                        }else {
                            tbProjectContact.setIsFirst(0);
                        }
                        String contactStr = "新增联系人'"+tbProjectContact.getName()+"'";
                        msg += StringUtils.isEmpty(msg)?contactStr:"，"+contactStr;
                        projectContactMapper.insert(tbProjectContact);
                    }
                    if (StringUtils.isNotEmpty(msg)){
                        changeStr += msg+"；";
                    }
                }
            }
            if (StringUtils.isNotEmpty(changeStr)){
                TbProjectOperRecord record = new TbProjectOperRecord();
                record.setProjectId(project.getProjectId());
                record.setMsg(changeStr);
                record.setCreateBy(project.getUpdateBy());
                record.setCreateTime(new Date());
                operRecordMapper.insert(record);
            }
            project.setUpdateTime(new Date());
            return baseMapper.updateTbProject(project);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public Boolean existedProjectName(Long projectId, String name) {
        boolean flag = false;
        QueryWrapper<TbProject> wrapper = new QueryWrapper<>();
        wrapper.eq("name", name);
        if (projectId!=null){
            wrapper.eq("project_id",projectId);
        }
        List<TbProject> projects = baseMapper.selectList(wrapper);
        if(projectId==null && projects.size()==0){
            flag = true;
        }
        if(projectId!=null){
            TbProject project = baseMapper.selectById(projectId);
            if(projects!=null && projects.size()>0){
                if(project.getName().equals(projects.get(0).getName())){
                    flag = true;
                }
            }
            if(projects.size()==0){
                flag = true;
            }
        }
        return flag;
    }

    @Override
    public AjaxResult deleteProject(Long projectId) {
        TbProject project = this.baseMapper.selectById(projectId);
        if("1".equals(project.getStatus())){
            this.baseMapper.deleteById(projectId);
            return AjaxResult.success();
        }else {
            return AjaxResult.error("项目已启动，无法删除！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addProgressRate(TbProjectProgressRate progressRate) {
        progressRate.setCreateTime(new Date());
        int row = progressRateMapper.insert(progressRate);
        TbProject project = baseMapper.selectById(progressRate.getProjectId());
        project.setProgressRate(progressRate.getProgressRate());
        project.setUpdateBy(progressRate.getCreateBy());
        project.setUpdateTime(new Date());
        baseMapper.updateTbProject(project);
        return row;
    }

    @Override
    public List<Map<String, Object>> getWorkHourList(Long projectId) {
        List<Map<String, Object>> list = new ArrayList<>();
        TbProject project = baseMapper.selectById(projectId);
        Long[] userIds = Convert.toLongArray(project.getPersonIds());
        for (Long userId : userIds) {
            Map<String, Object> map = new HashMap<>();
            SysUser user = userMapper.selectUserById(userId);
            if (user!=null && user.getIsBoss()==0){
                map.put("name",user.getUserName());
                map.put("userId",user.getUserId());
                SysDept dept = sysDeptMapper.selectDeptById(user.getDeptId());
                map.put("deptName",dept.getDeptName());
                Map<String, Object> dataMap = dailyReportMapper.selectUserWorkHour(user.getUserName(), projectId);
                map.put("workHours",dataMap.get("workHours"));
                list.add(map);
            }
        }
        return list;
    }

    @Override
    public void exportWorkHourList(Long projectId, HttpServletResponse response) {
        try {
            TbProject project = baseMapper.selectById(projectId);
            String fileName = project.getName()+"工时统计";
            HSSFWorkbook wb = new HSSFWorkbook();
            // 建立新的sheet对象（excel的表单） 并设置sheet名字
            HSSFSheet sheet = wb.createSheet();
            sheet.setDefaultRowHeightInPoints(30);// 设置缺省列高sheet.setDefaultColumnWidth(20);//设置缺省列宽
            sheet.setDefaultColumnWidth(20);
            //----------------二级标题格样式----------------------------------
            HSSFCellStyle titleStyle2 = wb.createCellStyle();        //表格样式
            titleStyle2.setAlignment(HorizontalAlignment.CENTER);
            titleStyle2.setVerticalAlignment(VerticalAlignment.CENTER);
            titleStyle2.setBorderBottom(BorderStyle.THIN); //下边框
            titleStyle2.setBorderLeft(BorderStyle.THIN);//左边框
            titleStyle2.setBorderTop(BorderStyle.THIN);//上边框
            titleStyle2.setBorderRight(BorderStyle.THIN);//右边框
            Font ztFont2 = wb.createFont();
            ztFont2.setItalic(false);                     // 设置字体为斜体字
            ztFont2.setColor(Font.COLOR_NORMAL);            // 将字体设置为“红色”
            ztFont2.setFontHeightInPoints((short)10);    // 将字体大小设置为18px
            ztFont2.setFontName("宋体");             // 字体应用到当前单元格上
            ztFont2.setBold(true);     //加粗
            titleStyle2.setFont(ztFont2);

            //----------------单元格样式----------------------------------
            HSSFCellStyle cellStyle = wb.createCellStyle();        //表格样式
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
            cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
            cellStyle.setBorderTop(BorderStyle.THIN);//上边框
            cellStyle.setBorderRight(BorderStyle.THIN);//右边框
            Font cellFont = wb.createFont();
            cellFont.setItalic(false);                     // 设置字体为斜体字
            cellFont.setColor(Font.COLOR_NORMAL);            // 将字体设置为“红色”
            cellFont.setFontHeightInPoints((short)10);    // 将字体大小设置为18px
            cellFont.setFontName("宋体");             // 字体应用到当前单元格上
            //cellFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
            cellStyle.setFont(cellFont);
            cellStyle.setWrapText(true);//设置自动换行

            HSSFRow row = sheet.createRow(0);
            HSSFCell cell = row.createCell(0);
            cell.setCellValue("项目成员");
            cell.setCellStyle(titleStyle2);

            HSSFCell cell1 = row.createCell(1);
            cell1.setCellValue("累计工时（小时）");
            cell1.setCellStyle(titleStyle2);

            HSSFCell cell2 = row.createCell(2);
            cell2.setCellValue("所属部门");
            cell2.setCellStyle(titleStyle2);

            List<Map<String, Object>> list = this.getWorkHourList(projectId);
            if (list!=null && list.size()>0){
                for (int i = 0; i < list.size(); i++) {
                    HSSFRow rowdata = sheet.createRow(i+1);

                    HSSFCell cellData = rowdata.createCell(0);
                    cellData.setCellValue(list.get(i).get("name").toString());
                    cellData.setCellStyle(cellStyle);

                    HSSFCell cellData1 = rowdata.createCell(1);
                    cellData1.setCellValue(list.get(i).get("workHours").toString());
                    cellData1.setCellStyle(cellStyle);

                    HSSFCell cellData2 = rowdata.createCell(2);
                    cellData2.setCellValue(list.get(i).get("deptName").toString());
                    cellData2.setCellStyle(cellStyle);
                }
            }
            // 输出Excel文件
            OutputStream output = response.getOutputStream();
            response.reset();
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("Content-Type","application/force-download");
            fileName = fileName+".xls";
            String fileNameURL = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename="+fileNameURL+";"+"filename*=utf-8''"+fileNameURL);
            response.setContentType("application/msexcel");
            wb.write(output);
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<Map<String, String>> getProjectByUser() {
        Long userId = SecurityUtils.getUserId();
        return baseMapper.getProjectByUserId(userId);
    }

    @Override
    public AjaxResult getDetail(Long projectId) {
        TbProject project = baseMapper.getDetail(projectId);
        return AjaxResult.success(project);
    }

    @Override
    public List<TbProjectProgressRate> getProgressRateList(Long projectId) {
        return progressRateMapper.selectList(new QueryWrapper<TbProjectProgressRate>().eq("project_id", projectId).orderByDesc("create_time"));
    }

    @Override
    public AjaxResult getDeptUser() {
        List<SysDept> depts = deptMapper.selectList(new QueryWrapper<>());
        List<TreeSelect> treeSelects = deptService.buildDeptTreeSelect(depts);
        List<Map<String,Object>> userList = userMapper.selectMaps(new QueryWrapper<SysUser>().select("user_id as userId","user_name as userName","dept_id as deptId").ne("user_id",1).ne("user_name","人事"));
        List<TreeSelect> otherUserList = new ArrayList<>();
        tree(treeSelects,userList,otherUserList);
        if (otherUserList!=null && otherUserList.size()>0) {
            TreeSelect select = new TreeSelect();
            select.setId(0L);
            select.setLabel("其它");
            select.setChildren(otherUserList);
            treeSelects.get(0).getChildren().add(select);
        }
        return AjaxResult.success(treeSelects);

    }

    @Override
    public List<TbProjectOperRecord> getProjectOperList(Long projectId) {
        return operRecordMapper.selectList(new QueryWrapper<TbProjectOperRecord>().eq("project_id", projectId).orderByDesc("create_time"));
    }

    public void tree(List<TreeSelect> deptTreeList,List<Map<String,Object>> userList,List<TreeSelect> otherUserList){
        if (deptTreeList!=null && deptTreeList.size()>0){
            for (TreeSelect treeSelect : deptTreeList) {
                if (treeSelect.getChildren()!=null && treeSelect.getChildren().size()>0) {
                    List<TreeSelect> childrenTreeList = treeSelect.getChildren();
                    Iterator<Map<String,Object>> iterator = userList.iterator();
                    while (iterator.hasNext()) {
                        Map<String,Object> sysUser = iterator.next();
                        if (StringUtils.isNotEmpty(sysUser.get("deptId").toString()) && sysUser.get("deptId").equals(treeSelect.getId())){
                            TreeSelect select = new TreeSelect();
                            select.setId(Long.parseLong(sysUser.get("userId").toString()));
                            select.setLabel(sysUser.get("userName").toString());
                            otherUserList.add(select);
                            iterator.remove();
                        }
                    }
                    tree(childrenTreeList,userList,otherUserList);
                }else{
                    List<TreeSelect> childList = new ArrayList<>();
                    Iterator<Map<String,Object>> iterator = userList.iterator();
                    while (iterator.hasNext()) {
                        Map<String,Object> sysUser = iterator.next();
                        if (StringUtils.isNotEmpty(sysUser.get("deptId").toString()) && sysUser.get("deptId").equals(treeSelect.getId())){
                            TreeSelect select = new TreeSelect();
                            select.setId(Long.parseLong(sysUser.get("userId").toString()));
                            select.setLabel(sysUser.get("userName").toString());
                            childList.add(select);
                            iterator.remove();
                        }
                    }
                    treeSelect.setChildren(childList);
                }
            }
        }
    }

    public String contrastObj(TbProject pojo1, TbProject pojo2) throws IllegalAccessException, IntrospectionException, InvocationTargetException {
        String msg = "";
        Class clazz = pojo1.getClass();
        Field[] fields = pojo1.getClass().getDeclaredFields();
        int i = 1;
        for (Field field : fields) {
            if ("serialVersionUID".equals(field.getName())) {
                continue;
            }
            PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
            Method getMethod = pd.getReadMethod();
            Object o1 = getMethod.invoke(pojo1);
            Object o2 = getMethod.invoke(pojo2);
            if (o1 == null || o2 == null) {
                continue;
            }
            if (!o1.toString().equals(o2.toString())) {
                if (field.getAnnotation(ApiModelProperty.class) != null) {
                    String fieldValue = field.getAnnotation(ApiModelProperty.class).value();
                    if(field.getAnnotation(Dict.class)!=null){
                        String dictName = field.getAnnotation(Dict.class).dictDataSource();
                        if (dictName !=null) {
                            o1 = dictDataMapper.selectDictLabel(dictName,o1.toString());
                            o2 = dictDataMapper.selectDictLabel(dictName,o2.toString());
                        }
                    }
                    if (o1 instanceof Date) {
                        o1 = DateUtil.formatDate((Date) o1);
                        o2 = DateUtil.formatDate((Date) o2);
                    }
                    if (fieldValue.equals("项目负责人")){
                        o1 = userMapper.selectUserById(Long.parseLong(o1.toString())).getUserName();
                        o2 = userMapper.selectUserById(Long.parseLong(o2.toString())).getUserName();
                    }
                    if (fieldValue.equals("项目成员")){
                        o1 = userMapper.selectUserNamesByIds(o1.toString());
                        o2 = userMapper.selectUserNamesByIds(o2.toString());
                    }
                    msg += fieldValue +"由'"+o1+ "'变更为'" + o2+"'；";
                }
                i++;
            }
        }
        return msg;
    }

}
